package com.finance.util;

import com.opencsv.CSVReader;
import com.opencsv.exceptions.CsvValidationException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Component
public class CsvFileUtil {

    /**
     * 读取CSV文件内容
     *
     * @param filePath CSV文件路径
     * @return 包含所有行的列表，每行是一个Map，key为列名，value为对应的值
     */
    public List<Map<String, String>> readCsvFile(String filePath) {
        List<Map<String, String>> records = new ArrayList<>();
        String[] headers = null;
        boolean foundDataSection = false;
        boolean foundEndSection = false;

        try (CSVReader reader = new CSVReader(new InputStreamReader(new FileInputStream(filePath), "GBK"))) {
            String[] line;
            while ((line = reader.readNext()) != null) {
                // Skip empty lines
                if (line.length == 0 || (line.length == 1 && line[0].trim().isEmpty())) {
                    continue;
                }

                // Check for data section start
                if (!foundDataSection && line.length > 0 && line[0].contains("#--------------")) {
                    foundDataSection = true;
                    // Skip the empty line after the marker
                    reader.readNext();
                    // Read the next line which contains headers
                    headers = reader.readNext();
                    continue;
                }

                // Check for data section end
                if (foundDataSection && line.length > 0 && line[0].contains("#--------------数据结束--------------")) {
                    foundEndSection = true;
                    break;
                }

                // Process data rows
                if (foundDataSection && !foundEndSection && headers != null) {
                    Map<String, String> record = new HashMap<>();
                    for (int i = 0; i < headers.length; i++) {
                        if (i < line.length) {
                            record.put(headers[i], line[i]);
                        } else {
                            record.put(headers[i], "");
                        }
                    }
                    records.add(record);
                }
            }

            log.info("Successfully read {} records from CSV file: {}", records.size(), filePath);
            return records;
        } catch (IOException | CsvValidationException e) {
            log.error("Error reading CSV file: {}", filePath, e);
            throw new RuntimeException("Failed to read CSV file", e);
        }
    }

    /**
     * 读取CSV文件内容并转换为指定类型的对象列表
     *
     * @param filePath CSV文件路径
     * @param clazz 目标类型
     * @param <T> 泛型类型
     * @return 对象列表
     */
    public <T> List<T> readCsvFileAsObjects(String filePath, Class<T> clazz) {
        List<Map<String, String>> records = readCsvFile(filePath);
        List<T> objects = new ArrayList<>();

        for (Map<String, String> record : records) {
            try {
                T object = clazz.getDeclaredConstructor().newInstance();
                // 使用反射设置对象属性
                for (Map.Entry<String, String> entry : record.entrySet()) {
                    try {
                        java.lang.reflect.Field field = clazz.getDeclaredField(entry.getKey());
                        field.setAccessible(true);
                        // 根据字段类型进行转换
                        if (field.getType() == String.class) {
                            field.set(object, entry.getValue());
                        } else if (field.getType() == Integer.class || field.getType() == int.class) {
                            field.set(object, Integer.parseInt(entry.getValue()));
                        } else if (field.getType() == Long.class || field.getType() == long.class) {
                            field.set(object, Long.parseLong(entry.getValue()));
                        } else if (field.getType() == Double.class || field.getType() == double.class) {
                            field.set(object, Double.parseDouble(entry.getValue()));
                        } else if (field.getType() == Boolean.class || field.getType() == boolean.class) {
                            field.set(object, Boolean.parseBoolean(entry.getValue()));
                        }
                    } catch (NoSuchFieldException e) {
                        log.warn("Field not found in class {}: {}", clazz.getName(), entry.getKey());
                    }
                }
                objects.add(object);
            } catch (Exception e) {
                log.error("Error converting record to object: {}", record, e);
            }
        }

        return objects;
    }
} 